#include "viewOpenGl.h"
#include <QProgressBar>
#include <QMessageBox>
#include "../Typecube.h"
#include "../SCL/ccl.h"

viewOpenGl::viewOpenGl(QWidget *parent):
  near_plane(0.2f),
  far_plane(500.0f),
  eyeX(0.),
  eyeY(0.),
  eyeZ(2.),
  camX(1.),
  camY(1.),
  camZ(10.),
  phy(0.0),
  theta(0.0)
{
  parent->resize ( 880, 780) ;
  bLoading = false;
  keyActive.reset() ;
  keySpeed = 51 ;
  keyIncrement = 1.51 ;
  connect(&keyTimer, SIGNAL(timeout()), this, SLOT(keyIdle()));
  keyTimer.start(keySpeed);

}

viewOpenGl::~viewOpenGl() {

    std::vector<CCube *>::iterator it;
    for (it=cube.begin() ; it != cube.end() ; ++it) {
        delete *it;
    }
    cube.clear() ;
}

void viewOpenGl::initGL() {
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST) ;



}


void viewOpenGl::initObject3D() {
    SCL::CCL Thread;
  Thread.display();
    QProgressBar ProgressBar (this);
    int iMaximum = 400;
    ProgressBar.setMinimum(0);
    ProgressBar.setMaximum(100);
    ProgressBar.setAlignment(Qt::AlignCenter);
    ProgressBar.setVisible(true);
    DemTerra.loadDem("rsc/data/Terrain.dem", 880, 780);
    int iCount = 0;
    int iCurrent = 0;
    int iPast = 0;
    ProgressBar.setValue(iPast);
    int iHeight;
    for (int i=0 ; i < 20 ; ++i) {
        for (int j=0 ; j < 20 ; ++j) {
         cube.push_back(new CCube ("rsc/shader/ToonShader.vert",
                                    "rsc/shader/ToonShader.frag"));
          iHeight = (DemTerra.refData(i+50, j+50)-2000)/100;
          cube.back()->setPosition(i, iHeight, j);
          if (iHeight >= 4) {
              cube.back()->setType(Cube::TERRE);
          } else if (iHeight == 3) {
            cube.back()->setType(Cube::SABLE);
          }else if (iHeight == 2) {
              cube.back()->setType(Cube::EAU);
          } else if (iHeight == 1){
              cube.back()->setType(Cube::PIERRE);
          }else {
              cube.back()->setType(Cube::LAVE);
          }
          cube.back()->Initialize();
          cube.back()->addMatrix("ModelProjectionMatrix", &matProjection)  ;
          cube.back()->addMatrix("ModelViewMatrix",  &matModelview )  ;
          iCount++;
          iCurrent = iCount*100;
          iCurrent /= iMaximum;
          if (iPast!= iCurrent) {
              iPast = iCurrent;
              ProgressBar.setValue(iPast);
          }

        }
    }
     ProgressBar.setValue(100);

}
bool viewOpenGl::callback_idle(){
    if (cube.empty() && bLoading) {
        initObject3D();
        bLoading = false;
    }

  return true ;
}

void viewOpenGl::callback_reshape(int _width, int _height) {
  glViewport(0.,0.,_width, _height);
   matProjection.setPerspective (65.0f,(float)_width/(float)_height,near_plane,far_plane) ;
}

void viewOpenGl::callback_display() {
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glClearColor(0.0, 0.0, 0.0, 1.0) ;
  matModelview.setLookAt(eyeX, eyeY, eyeZ, eyeX+10*camX,eyeY+10*camY,eyeZ+10*camZ, 0.0 , 1.0 ,0.0) ;
  std::vector<CCube *>::iterator it;
  for (it=cube.begin() ; it != cube.end() ; ++it) {
      (*it)->Play();
  }
}


  void viewOpenGl::keyPressEvent ( QKeyEvent * event ) {

    switch (event->key()) {
      case Qt::Key_Up:
        bLoading = true;
        keyActive[0] = true ;
      break;
      case Qt::Key_Down:
        keyActive[1] = true ;
      break;
      case Qt::Key_Left:
        keyActive[2] = true ;
      break;
      case Qt::Key_Right:
        keyActive[3] = true ;
      break;
      case Qt::Key_Space:
        keyActive[4] = true ;
      break;
      case Qt::Key_0:
        keyActive[5] = true ;
       break;
    }
  }
  
  void viewOpenGl::keyReleaseEvent ( QKeyEvent * event ) {
    switch (event->key()) {
      case Qt::Key_Up:
        keyActive[0] = false ;
      break;
      case Qt::Key_Down:
        keyActive[1] = false ;
      break;
      case Qt::Key_Left:
        keyActive[2] = false ;
      break;
      case Qt::Key_Right:
        keyActive[3] = false ;
      break;
    case Qt::Key_Space:
      keyActive[4] = false ;
    break;
    case Qt::Key_0:
      keyActive[5] = false ;
     break;
    }
  }

  bool viewOpenGl::keyIdle() {

    if(keyActive[0]) {
        eyeX = eyeX+camX/keyIncrement;
        eyeZ = eyeZ+camZ/keyIncrement;
    }

    if(keyActive[1]) {
        eyeX = eyeX-camX/keyIncrement;
        eyeZ = eyeZ-camZ/keyIncrement;
    }

    if(keyActive[2]) {
        eyeX = eyeX+camZ/keyIncrement ;
        eyeZ = eyeZ-camX/keyIncrement ;
    }

    if(keyActive[3]) {
        eyeX = eyeX-camZ/keyIncrement ;
        eyeZ = eyeZ+camX/keyIncrement ;
    }

    if(keyActive[4]) {
        eyeY ++;
    }

    if(keyActive[5]) {
        eyeY --;
    }

    return true ;
  }

  void viewOpenGl::mouseMoveEvent ( QMouseEvent * event ) {

    int x = event->x() ;
    int y = event->y() ;
    // Get the center of the screen
    int middleX=width()/2;
    int middleY=height()/2;


    if ((x==middleX) && (y==middleY))
        return;

//     // Set the curosr pos to the center of the screen
//     glutWarpPointer(middleX,middleY);

    // Sensivity of the mouse movements
    float sensivity=0.00005;

    float thetaX = (float)( (middleY - y) ) * sensivity;
    float thetaY = (float)( (middleX - x) ) * sensivity;

    // Get the direction the mouse moved in
    if ((phy+thetaY> 2*M_PI) || (phy+thetaY< -2*M_PI))
        phy=0;

    if ((!(theta+thetaX > M_PI/3)) && (!(theta+thetaX < -M_PI/3)))
        theta += thetaX;


    phy-= thetaY;
    // Update the direction where the camera is looking at
    camX=cos(phy)*cos(theta);
    camY=sin(theta);
    camZ=cos(theta)*sin(phy);
  }


